package com.biz.primus.ms.search.service;

import com.biz.primus.base.constant.Constant;
import com.biz.primus.base.elasticsearch.entities.ProductEntity;
import com.biz.primus.base.elasticsearch.repository.ProductEsRepository;
import com.biz.primus.base.elasticsearch.util.PageUtil;
import com.biz.primus.base.enums.SearchChannel;
import com.biz.primus.base.enums.search.ProductSearchSort;
import com.biz.primus.base.enums.vendor.VendorType;
import com.biz.primus.base.vo.*;
import com.biz.primus.base.vo.commodity.SaleStatus;
import com.biz.primus.common.utils.StringUtil;
import com.biz.primus.common.utils.kmeans.KMeans;
import com.biz.primus.common.vo.KMeansRangeVo;
import com.biz.primus.ms.search.feign.DepotFeignClient;
import com.biz.primus.ms.search.feign.ProductIdxFeignClient;
import com.biz.primus.ms.search.feign.WeightFeignClient;
import com.biz.primus.ms.search.vo.ProductSortVo;
import com.biz.primus.search.vo.search.ProductSearchResultVo;
import com.biz.primus.search.vo.search.SearchFieldVo;
import com.biz.primus.search.vo.search.SearchProductRequestVo;
import com.biz.primus.search.vo.search.VendorProductRespVo;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.StopWatch;
import org.elasticsearch.common.lucene.search.function.FieldValueFactorFunction;
import org.elasticsearch.index.query.*;
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders;
import org.elasticsearch.index.query.functionscore.fieldvaluefactor.FieldValueFactorFunctionBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

import static com.biz.primus.base.constant.Constant.DEFAULT_PRICE_NAME;
import static org.elasticsearch.index.query.QueryBuilders.*;

@Service
@Slf4j
public class ProductSearchService {

    private static final long serialVersionUID = -1673071910992652238L;

    private LoadingCache<String, KeywordWeightVo> weightConfigCatch = CacheBuilder.newBuilder().initialCapacity(20).expireAfterWrite(10, TimeUnit.SECONDS)
            .build(new CacheLoader<String, KeywordWeightVo>() {

                public KeywordWeightVo load(String key) throws Exception {
                    KeywordWeightVo config;
                    if (keywordWeightService == null) {
                        log.warn("无法连接商品服务获取搜索权重");
                        config = new KeywordWeightVo();
                        config.defaultInit();
                        return config;
                    }
                    config = keywordWeightService.config();
                    if (config == null) {
                        config = new KeywordWeightVo();
                        config.defaultInit();
                        log.warn("获取搜索权重为空,返回默认配置");
                        return config;
                    }
                    return config;
                }
            });


    private KeywordWeightVo weightConfig() {
        return KeywordWeightVo.getInstance();
    }

    @Autowired
    private WeightFeignClient keywordWeightService;

    @Autowired
    private ProductEsRepository productEsRepository;

    @Autowired
    private ProductIdxFeignClient productIdxService;

    @Autowired
    private DepotFeignClient depotService;

    public ProductSearchResultVo<ProductSearchResultEntityVo> searchProduct(SearchProductRequestVo vo) {
        if (log.isDebugEnabled()) {
            log.debug("ProductEsRepositoryImpl#searchProduct param vo: {}", vo);
        }
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        BoolQueryBuilder rootQueryBuilder = QueryBuilders.boolQuery();
        //打分策略
        FunctionScoreQueryBuilder functionScoreQueryBuilder = null;
        String keyword = StringUtil.patternMatcherStr(Optional.ofNullable(vo.getKeyword()).orElse(""));
        Boolean isSku = Boolean.FALSE;
        isSku = isSku(keyword, isSku);
        //打分排序只针对默认排序
        if (StringUtils.isNotBlank(keyword) && !isSku) {
            functionScoreQueryBuilder = QueryBuilders.functionScoreQuery(QueryBuilders
                    .queryStringQuery(keyword)
                    .defaultField("name")
                    .analyzer("ik")
                    .minimumShouldMatch("2<60%"))
                    .scoreMode("sum")
                    .boostMode("multiply");
        } else {
            functionScoreQueryBuilder = QueryBuilders.functionScoreQuery().scoreMode("sum").boostMode("multiply");
            if (StringUtils.isNotBlank(vo.getKeyword())) {
                rootQueryBuilder.must(QueryBuilders.termQuery("productCode", vo.getKeyword()));
            }
        }
        //上下架
        TermQueryBuilder saleStatus = QueryBuilders.termQuery("saleStatus", SaleStatus.ON_SALE.getValue());
        rootQueryBuilder.must(saleStatus);
        if (vo.getSearchChannel() != null) {
            if (Objects.equals(vo.getSearchChannel(), SearchChannel.APP)) {
                TermQueryBuilder appSaleStatusTerm = QueryBuilders.termQuery("appSaleStatus", SaleStatus.ON_SALE.getValue());
                rootQueryBuilder.must(appSaleStatusTerm);
            } else if (Objects.equals(vo.getSearchChannel(), SearchChannel.WECHAT_MALL)) {
                TermQueryBuilder webSaleStatusTerm = QueryBuilders.termQuery("webSaleStatus", SaleStatus.ON_SALE.getValue());
                rootQueryBuilder.must(webSaleStatusTerm);
            }
        }
        // 根据类型构建搜索
        buildTypeSearch(vo, rootQueryBuilder);

        // 关键字搜索
        buildKeyWordSearch(vo, keyword, functionScoreQueryBuilder,rootQueryBuilder);

//        是否分页搜索
        if (Objects.equals(vo.getPage(), Constant.NO_PAGE_FLAG) || isSku) {
            nativeSearchQueryBuilder.withQuery(rootQueryBuilder);
            nativeSearchQueryBuilder.withPageable(new PageRequest(0, 10000));
            return this.doSearch(nativeSearchQueryBuilder.build());
        } else {
            // 排序规则初始化

            ProductSortVo productSort = this.getProductSort(DEFAULT_PRICE_NAME, vo.getSort());
//            排序规则
            buildSortAndPage(vo, nativeSearchQueryBuilder, rootQueryBuilder, keyword, productSort, functionScoreQueryBuilder);


            // 过滤分类
            if (vo.getCategoryId() != null) {
                TermQueryBuilder categoryTerm = QueryBuilders.termQuery("category", vo.getCategoryId());
                rootQueryBuilder.filter(categoryTerm);
            }

            // 过滤条件
            this.fillQueryToQueryBuilder(rootQueryBuilder, DEFAULT_PRICE_NAME, vo.getFields());
            nativeSearchQueryBuilder.withQuery(rootQueryBuilder);
            log.info("search query {}", rootQueryBuilder.toString());
            return this.doSearch(nativeSearchQueryBuilder.build());
        }
    }

    private Boolean isSku(String keyword, Boolean isSku) {
        return Boolean.FALSE;
    }

    public SearchResult<Long> searchBrandByCategoryId(SearchProductRequestVo vo) {
        if (log.isDebugEnabled()) {
            log.debug("ProductEsRepositoryImpl#searchBrandByCategoryId param vo: {}", vo);
        }
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        BoolQueryBuilder rootQueryBuilder = QueryBuilders.boolQuery();
        // 根据类型构建搜索
        buildTypeSearch(vo, rootQueryBuilder);

        //过滤分类
        TermQueryBuilder categoryTerm = QueryBuilders.termQuery("category", vo.getCategoryId());
        rootQueryBuilder.must(categoryTerm);
        nativeSearchQueryBuilder.withQuery(rootQueryBuilder);
        nativeSearchQueryBuilder.withPageable(new PageRequest(0, 10000));

        List<Long> brandList = Lists.newArrayList();
        Iterable<ProductEntity> itr = this.productEsRepository.search(nativeSearchQueryBuilder.build());
        if (itr != null) {
            for (ProductEntity index : itr) {
                brandList.add(index.getBrand());
            }
        }
        HashSet<Long> brandIdsSet = new HashSet<>(brandList);
        brandList = Lists.newArrayList(brandIdsSet);
        SearchResult<Long> resp = new SearchResult<>();
        resp.setItems(brandList);
        return resp;
    }

    /**
     * 立即送模式排序和分页
     *
     * @param vo
     * @param nativeSearchQueryBuilder
     * @param rootQueryBuilder
     * @param keyword
     * @param productSort
     * @param functionScoreQueryBuilder
     */
    private void buildSortAndPage(SearchProductRequestVo vo, NativeSearchQueryBuilder nativeSearchQueryBuilder,
                                  BoolQueryBuilder rootQueryBuilder, String keyword, ProductSortVo productSort,
                                  FunctionScoreQueryBuilder functionScoreQueryBuilder) {
        FieldSortBuilder fieldSortBuilder1 = null;
        FieldSortBuilder fieldSortBuilder2 = null;
        PageRequest page;
        switch (vo.getSort().getDescription()) {
            case "defaultSort":
                if (keyword != null && StringUtils.isNotBlank(keyword)) {
                    functionScoreQueryBuilder.add(new FieldValueFactorFunctionBuilder("salesVolume").modifier(FieldValueFactorFunction.Modifier.LOG1P).factor(weightConfig().getSalesVolumeSortWeight().floatValue()));
                    functionScoreQueryBuilder.add(new FieldValueFactorFunctionBuilder("globalIdx").factor(weightConfig().getSalesVolumeSortWeight().floatValue()));
                    rootQueryBuilder.must(functionScoreQueryBuilder);
                    log.debug("DepotProductSearchService searchDepotProduct defaultSort sort:_score_DESC");
                } else {
                    log.debug("DepotProductSearchService searchDepotProduct defaultSort sort:globalIdx+virtualSales_DESC");
                    fieldSortBuilder1 = SortBuilders.fieldSort("globalIdx").order(SortOrder.DESC);
                    fieldSortBuilder2 = SortBuilders.fieldSort("salesVolume").order(SortOrder.DESC);
                }
                break;
            case "salesVolumeDesc":
                log.debug("DepotProductSearchService searchDepotProduct defaultSort sort:globalIdx+virtualSales_DESC");
                fieldSortBuilder1 = SortBuilders.fieldSort("globalIdx").order(SortOrder.DESC);
                fieldSortBuilder2 = SortBuilders.fieldSort("salesVolume").order(SortOrder.DESC);
                break;
            case "salesVolumeAsc":
                fieldSortBuilder1 = SortBuilders.fieldSort("salesVolume").order(SortOrder.ASC);
                break;
            case "salePriceDesc":
                fieldSortBuilder1 = SortBuilders.fieldSort(productSort.getSortFieldName()).order(SortOrder.DESC);
                break;
            case "salePriceAsc":
                fieldSortBuilder1 = SortBuilders.fieldSort(productSort.getSortFieldName()).order(SortOrder.ASC);
                break;
            case "updateTimeDesc":
                fieldSortBuilder1 = SortBuilders.fieldSort("updateTimestamp").order(SortOrder.DESC);
                break;
            default:
                break;
        }
        page = PageUtil.getPageResult(vo.getPage(), vo.getPageSize());
        nativeSearchQueryBuilder.withPageable(page);
        if (fieldSortBuilder1 != null) {
            nativeSearchQueryBuilder.withSort(fieldSortBuilder1);
        }
        if (fieldSortBuilder2 != null) {
            nativeSearchQueryBuilder.withSort(fieldSortBuilder2);
        }
    }

    private void buildKeyWordSearch(SearchProductRequestVo vo, String keyword, FunctionScoreQueryBuilder functionScoreQueryBuilder, BoolQueryBuilder rootQueryBuilder) {
        if (StringUtils.isNotBlank(vo.getKeyword())) {
            functionScoreQueryBuilder
                    .add(QueryBuilders.queryStringQuery(keyword).defaultField("name").analyzer("ik").minimumShouldMatch("4<80%"), ScoreFunctionBuilders.weightFactorFunction(weightConfig().getProductNameWeight().floatValue()));
        }
        if (vo.getSort() != ProductSearchSort.DEFAULT_SORT && StringUtils.isNotBlank(keyword)) {
            //如果查询不为默认排序,且为关键词搜索
            rootQueryBuilder.must(QueryBuilders.queryStringQuery(keyword).defaultField("name")
                    .defaultOperator(QueryStringQueryBuilder.Operator.OR).analyzer("ik").minimumShouldMatch("4<60%"));
        }

    }

    private void buildTypeSearch(SearchProductRequestVo vo, BoolQueryBuilder rootQueryBuilder) {
        if (vo.getType() != null) {
            // 生成查询 A 类商品或者 B 类商品查询
            if (log.isDebugEnabled()) {
                log.debug("product type is not null, type: {}", vo.getType());
            }
            if (vo.getType() == VendorType.TYPE_A.getValue()) {
                typeASearchBuilder(vo, rootQueryBuilder);
            } else {
                typeBSearchBuilder(vo, rootQueryBuilder);

            }
        } else {
            typeABSearchBuilder(vo, rootQueryBuilder);
        }
    }

    private void typeABSearchBuilder(SearchProductRequestVo vo, BoolQueryBuilder rootQueryBuilder) {
        BoolQueryBuilder typeQueryBuiler = QueryBuilders.boolQuery();
        BoolQueryBuilder aTypeQueryBuilder = QueryBuilders.boolQuery();
        TermQueryBuilder aTypeTerm = QueryBuilders.termQuery("productType", VendorType.TYPE_A.getValue());
        BoolQueryBuilder bTypeQueryBuilder = QueryBuilders.boolQuery();
        TermQueryBuilder bTypeTerm = QueryBuilders.termQuery("productType", VendorType.TYPE_B.getValue());

        // 过滤库存(A类商品有无货都显示)
        RangeQueryBuilder stockRangeA = QueryBuilders.rangeQuery("stock");
        stockRangeA.gt(0);
        aTypeQueryBuilder.must(stockRangeA);
        aTypeQueryBuilder.must(aTypeTerm);

        // 过滤库存(B类商品只显示有货的)
        RangeQueryBuilder stockRangeB = QueryBuilders.rangeQuery("stock");
        stockRangeB.gt(0);
        RangeQueryBuilder stockChannel = QueryBuilders.rangeQuery("stockChannel");
        stockChannel.gt(0);
        BoolQueryBuilder should = QueryBuilders.boolQuery().should(stockRangeB).should(stockChannel);

        bTypeQueryBuilder.must(should);
        bTypeQueryBuilder.must(bTypeTerm).must(QueryBuilders.matchPhraseQuery("depotCode", vo.getDepotCode()));
        //TODO 编译错误
//        if (vo.getVendorId() != null) {
//            // 如果是 A 类商品, 过滤 vendorId
//            TermQueryBuilder vendorTerm = QueryBuilders.termQuery("vendorId", vo.getVendorId());
//            aTypeQueryBuilder.must(vendorTerm);
//            bTypeQueryBuilder.must(vendorTerm);
//        }
//
//        // 过滤 Geo 信息
//        if (vo.getGeoId() != null) {
//            QueryStringQueryBuilder geoStringQueryBuilder = QueryBuilders.queryStringQuery(String.valueOf(vo.getGeoId()));
//            geoStringQueryBuilder.field("geoIds").analyzer("ik_smart");
//            aTypeQueryBuilder.must(geoStringQueryBuilder);
//        }

        //上架过滤
        TermQueryBuilder saleStatusTerm = QueryBuilders.termQuery("saleStatus", SaleStatus.ON_SALE.getValue());
        // 为开启快喝模式, B类商品选择省仓门店的商品
        typeQueryBuiler.should(aTypeQueryBuilder).should(bTypeQueryBuilder);
        typeQueryBuiler.must(saleStatusTerm);
        rootQueryBuilder.filter(typeQueryBuiler);
    }

    private void typeBSearchBuilder(SearchProductRequestVo vo, BoolQueryBuilder rootQueryBuilder) {
        // 如果是 B 类商品, 过滤 vendorId 和 depotID
        BoolQueryBuilder bTypeQueryBuilder = QueryBuilders.boolQuery();
        TermQueryBuilder bTypeTerm = QueryBuilders.termQuery("productType", VendorType.TYPE_B.getValue());
        bTypeQueryBuilder.must(bTypeTerm).must(QueryBuilders.matchPhraseQuery("depotCode", vo.getDepotCode()));
        if (vo.getDepotProduct() != null && vo.getDepotProduct()) {
            //立即送
            immediateSearchBuilder(rootQueryBuilder, bTypeQueryBuilder);
        } else {
            //普通送
            normalSendSearchBuilder(vo, rootQueryBuilder, bTypeQueryBuilder);
        }
        rootQueryBuilder.filter(bTypeQueryBuilder);
    }

    /**
     * @param vo
     * @param rootQueryBuilder
     * @param bTypeQueryBuilder
     */
    private void normalSendSearchBuilder(SearchProductRequestVo vo, BoolQueryBuilder rootQueryBuilder, BoolQueryBuilder bTypeQueryBuilder) {
        // 过滤库存(B类商品只显示有货的)  省仓门店  一个有货即可
        RangeQueryBuilder stockRange = QueryBuilders.rangeQuery("stock");
        stockRange.gt(0);
        bTypeQueryBuilder.must(stockRange);
        //TODO 编译错误
//        if (vo.getVendorId() != null) {
//            TermQueryBuilder vendorTerm = QueryBuilders.termQuery("vendorId", vo.getVendorId());
//            bTypeQueryBuilder.must(vendorTerm);
//        }
    }

    /**
     * 立即送
     *
     * @param rootQueryBuilder
     * @param bTypeQueryBuilder
     */
    private void immediateSearchBuilder(BoolQueryBuilder rootQueryBuilder, BoolQueryBuilder bTypeQueryBuilder) {
//            查询门店必须有库存
        RangeQueryBuilder stockRange = QueryBuilders.rangeQuery("depotStock");
        stockRange.gt(0);
        bTypeQueryBuilder.must(stockRange);
    }

    private void typeASearchBuilder(SearchProductRequestVo vo, BoolQueryBuilder rootQueryBuilder) {
        // 官网A类和B类商品上架标识 非门店上架标识 过滤上架状态(仅显示已上架商品)
        TermQueryBuilder saleStatusTerm = QueryBuilders.termQuery("saleStatus", SaleStatus.ON_SALE.getValue());
        rootQueryBuilder.must(saleStatusTerm);

        BoolQueryBuilder aTypeQueryBuilder = QueryBuilders.boolQuery();
        TermQueryBuilder aTypeTerm = QueryBuilders.termQuery("productType", VendorType.TYPE_A.getValue());
        aTypeQueryBuilder.must(aTypeTerm);
        //TODO 编译错误
//        if (vo.getVendorId() != null) {
//            // 如果是 A 类商品, 过滤 vendorId
//            TermQueryBuilder vendorTerm = QueryBuilders.termQuery("vendorId", String.valueOf(vo.getVendorId()));
//            aTypeQueryBuilder.must(vendorTerm);
//        }
//
//        // 过滤 Geo 信息
//        if (vo.getGeoId() != null) {
//            QueryStringQueryBuilder geoStringQueryBuilder = QueryBuilders.queryStringQuery(String.valueOf(vo.getGeoId()));
//            geoStringQueryBuilder.field("geoIds").analyzer("ik_smart");
//            aTypeQueryBuilder.must(geoStringQueryBuilder);
//        }

        // 过滤库存(A类商品有无货都要显示)
        RangeQueryBuilder stockRange = QueryBuilders.rangeQuery("stock");
        stockRange.gte(0);
        aTypeQueryBuilder.must(stockRange);

        // 为开启快喝模式, B类商品选择省仓门店的商品
        rootQueryBuilder.filter(aTypeQueryBuilder);
    }


    /**
     * 搜索商品
     *
     * @return 商品搜索结果Vo
     */
    private ProductSearchResultVo<ProductSearchResultEntityVo> doSearch(NativeSearchQuery nativeSearchQuery) {
        StopWatch watcher = new StopWatch();
        watcher.start();
        ProductSearchResultVo<ProductSearchResultEntityVo> searchResult = new ProductSearchResultVo<>();
        Page<ProductEntity> page = this.productEsRepository.search(nativeSearchQuery);
        List<ProductSearchResultEntityVo> entityVos = Lists.newArrayList();
        if (page != null) {
            List<ProductEntity> productEntities = page.getContent();
            productEntities.stream().filter(Objects::nonNull).forEach((p) -> {
                entityVos.add(new ProductSearchResultEntityVo(Long.valueOf(p.getProductId()), p.getProductCode(), p.getProductType()));
            });
            searchResult.setItems(entityVos);
            searchResult.setTotalElements(page.getTotalElements());
            searchResult.setTotalPages(page.getTotalPages());
        }
        watcher.split();
        watcher.stop();
        if (log.isDebugEnabled()) {
            log.debug("searchResult after search: {}", searchResult.toString());
        }

        log.debug("search product split: {}ms", watcher.getSplitTime());

        return searchResult;
    }

    private List<ProductFieldVo> filterAndSortFields(List<ProductFieldVo> fieldVos, List<String> filterFields) {
        if (CollectionUtils.isEmpty(filterFields)) {
            return fieldVos;
        }

        List<ProductFieldVo> resultFiledVos = Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(fieldVos) || CollectionUtils.isNotEmpty(filterFields)) {
            for (String filterField : filterFields) {
                for (ProductFieldVo fieldVo : fieldVos) {
                    if (Objects.equals(filterField, fieldVo.getLabel())) {
                        resultFiledVos.add(fieldVo);
                        break;
                    }
                }
            }
        }
        return resultFiledVos;
    }

    private ProductFieldVo getPriceFieldVo(List<Double> prices) {
        StopWatch watcher = new StopWatch();
        watcher.start();
        List<KMeansRangeVo> priceRanges = new KMeans(prices).getRanges("%d-%d");
        watcher.stop();
        log.debug("Kmeans cost：{} ms", watcher.getTime());
        ProductFieldVo fieldVo = new ProductFieldVo();
        fieldVo.setField("price");
        fieldVo.setLabel("价格");
        List<ProductFieldItemVo> itemVos = Lists.newArrayList();
        for (KMeansRangeVo vo : priceRanges) {
            ProductFieldItemVo itemVo = new ProductFieldItemVo();
            itemVo.setValue(vo.getField());
            itemVos.add(itemVo);
        }
        fieldVo.setItems(itemVos);
        return fieldVo;
    }

    /**
     * 获取商品排序规则
     *
     * @param priceName 价格名称
     * @param sort      传入排序规则
     * @return 传出排序规则
     */
    private ProductSortVo getProductSort(String priceName, ProductSearchSort sort) {
        ProductSortVo productSort;
        switch (sort) {
            case ON_SALE_TIME_ASC:
                productSort = new ProductSortVo("onSaleTime", SortOrder.ASC);
                break;
            case ON_SALE_TIME_DESC:
                productSort = new ProductSortVo("onSaleTime", SortOrder.DESC);
                break;
            case SALE_PRICE_ASC:
                productSort = new ProductSortVo(priceName, SortOrder.ASC);
                break;
            case SALE_PRICE_DESC:
                productSort = new ProductSortVo(priceName, SortOrder.DESC);
                break;
            case SALES_VOLUME_ASC:
                productSort = new ProductSortVo("salesVolume", SortOrder.ASC);
                break;
            case SALES_VOLUME_DESC:
                productSort = new ProductSortVo("salesVolume", SortOrder.DESC);
                break;
            default:
                productSort = new ProductSortVo("salesVolume", SortOrder.DESC);
        }
        return productSort;
    }

    /**
     * 遍历搜索条件Vo
     *
     * @param root      es查询条件构造器
     * @param priceName 价格方法名
     * @param fieldVos  商品搜索过滤字段
     * @return es查询构造器
     */
    private void fillQueryToQueryBuilder(BoolQueryBuilder root, String priceName, List<SearchFieldVo> fieldVos) {
        if (CollectionUtils.isNotEmpty(fieldVos)) {
            for (SearchFieldVo fieldVo : fieldVos) {
                if (StringUtils.equals("price", fieldVo.getField())) {
                    // 过滤字段是价格
                    if (StringUtils.isNotBlank(fieldVo.getValue())) {
                        if (StringUtils.contains(fieldVo.getValue(), "_")) {
                            String[] prices = fieldVo.getValue().split("_");
                            RangeQueryBuilder priceQueryBuilder = new RangeQueryBuilder(priceName);
                            priceQueryBuilder.gte(Integer.parseInt(prices[0]));// 大于等于
                            if (prices.length == 2 && StringUtils.isNotBlank(prices[1])) {
                                priceQueryBuilder.lte(Integer.parseInt(prices[1]));// 小于等于
                            }
                            root.filter(priceQueryBuilder);
                        } else {
                            RangeQueryBuilder priceQueryBuilder = new RangeQueryBuilder(priceName);
                            priceQueryBuilder.gte(Integer.parseInt(fieldVo.getValue()));// 大于等于
                            priceQueryBuilder.lte(Integer.parseInt(fieldVo.getValue()));// 小于等于
                            root.filter(priceQueryBuilder);
                        }
                    }
                } else {
                    if (StringUtils.isNotBlank(fieldVo.getField()) && StringUtils.isNotBlank(fieldVo.getValue())) {
                        if (StringUtils.equals(fieldVo.getField(), "propertiesNested")) {
                            // 过滤字段是扩展属性
                            if (StringUtils.isNotBlank(fieldVo.getValue())) {
                                String[] keyAndValue = fieldVo.getValue().split("_");
                                if (keyAndValue.length == 2 && StringUtils.isNotBlank(keyAndValue[0]) && StringUtils.isNotBlank(keyAndValue[1])) {
                                    NestedQueryBuilder propertiesNested = nestedQuery("propertiesNested",
                                            boolQuery().must(
                                                    termQuery("propertiesNested.name", keyAndValue[0])
                                            ).must(
                                                    QueryBuilders.termsQuery("propertiesNested.value", keyAndValue[1].split(","))
                                            ));
                                    root.filter(propertiesNested);
                                }
                            }
                        } else {
                            // 过滤字段是商品的一般属性
                            if (fieldVo.getField().contains("not:")) {
                                root.filter(QueryBuilders.boolQuery().mustNot(QueryBuilders.termsQuery(
                                        fieldVo.getField().replace("not:", ""),
                                        fieldVo.getValue().split(","))));
                            } else {
                                //termsQuery Filters documents that have fields that match any of the provided terms (not analyzed).
                                root.filter(QueryBuilders.termsQuery(fieldVo.getField(), fieldVo.getValue().split(",")));
                            }
                        }
                    }
                }
            }
        }
    }

    public VendorProductRespVo getVendorProductSize(SearchProductRequestVo vo) {
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        BoolQueryBuilder rootQueryBuilder = QueryBuilders.boolQuery();
        // 根据类型构建搜索
        buildTypeSearch(vo, rootQueryBuilder);
        // 是否分页搜索
        nativeSearchQueryBuilder.withQuery(rootQueryBuilder);
        nativeSearchQueryBuilder.withPageable(new PageRequest(0, 10000));
        Iterable<ProductEntity> itr = this.productEsRepository.search(nativeSearchQueryBuilder.build());
        VendorProductRespVo respVo = new VendorProductRespVo();
        Integer size = 0;
        for (ProductEntity productEntity : itr) {
            size++;
        }
        respVo.setSize(size);
        return respVo;
    }


}
